package concurrency.basicthreading.demo;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


/**
 * 如果你希望从线程中返回结果，那么可以使实现Callable接口 Java SE5中引入的Callable接口是一个具有类型参数的泛型。
 * 它的参数类型就是从call方法中返回的类型。Callable接口中需要复写的是call方法而不是run方法。
 * 
 * run方法通过Thread对象的start方法调用，而call则是通过ExecutorService.submit()方法调用。
 */
public class Demo02Callable implements Callable<String> {

	private int integer = 0;
	public Demo02Callable(int i) {
		integer = i;
	}
	
	@Override
	public String call() throws Exception {
		int result = 0;
		for (int i = 0; i < integer; i++) {
			result += i;
			
		}
		Thread.sleep(1000 * integer);
		return "Thread #"  + Thread.currentThread().getId() + ": " + result;
	}

	public static void main(String[] args) {
		ExecutorService exec = Executors.newCachedThreadPool();
		
		ArrayList<Future<String>> results = new ArrayList<Future<String>>();
		
		/*
		for (int i = 100; i < 100000; i++) {
			//submit() 方法产生一个Future对象
			results.add(exec.submit(new Demo02Callable(i)));
		}
		
		exec.shutdown();
		
		for(Future<String> result : results) {
			try {
				System.out.println(result.get());
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}  finally {
				
			}
		}
		*/
		
		//submit() 方法产生一个Future对象
		results.add(exec.submit(new Demo02Callable(10)));
		results.add(exec.submit(new Demo02Callable(0)));
		exec.shutdown();

		/*
		 * Future.get() 方法将阻塞主线程， 直到结果准备就绪. 
		 * 下面的代码两个结果都将被打印到屏幕上。尽管results.get(1)比results.get(0)早算出结果。
		 *  但仍然按照顺序打印所有结果。
		 */
		try {
			System.out.println("result(0) is done:" + results.get(0).get());
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
		
		try {
			System.out.println("result(1) is done:" + results.get(1).get());
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
		
		/*
		 * 下面使用Future.isDone()方法来判断结果是否准备就绪，防止阻塞主线程。
		 * 下面的代码只打印results.get(1)中的结果。因为通过isDone()判断结果是否准备就绪， 
		 * results.get(0).get()  没有被执行。
		 

		if (results.get(0).isDone()){
			try {
				System.out.println("result(0) is done:" + results.get(0).get());
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		
		if (results.get(1).isDone()){
			try {
				System.out.println("result(1) is done:" + results.get(1).get());
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		*/
	}
}
